package ua.kharkiv.khpi.tarasenko.diploma.analysis.test;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import ua.kharkov.khpi.tarasenko.bach.analysis.prefixspan.Item;
import ua.kharkov.khpi.tarasenko.bach.analysis.prefixspan.Node;
import ua.kharkov.khpi.tarasenko.bach.analysis.prefixspan.PrefixSpanAlgorythm;
import ua.kharkov.khpi.tarasenko.bach.analysis.prefixspan.PseudoDbPS;
import ua.kharkov.khpi.tarasenko.bach.analysis.prefixspan.Sequence;
import ua.kharkov.khpi.tarasenko.bach.analysis.tnr.AlgoTNR;
import ua.kharkov.khpi.tarasenko.bach.analysis.tnr.PseudoDbTNR;
import ua.kharkov.khpi.tarasenko.bach.analysis.tnr.RedBlackTree;
import ua.kharkov.khpi.tarasenko.bach.analysis.tnr.RuleG;
import ua.kharkov.khpi.tarasenko.bach.analysis.utils.AnalysisUtils;
import ua.kharkov.khpi.tarasenko.bach.analysis.utils.FileUtils;
import ua.kharkov.khpi.tarasenko.bach.core.EShopException;
import ua.kharkov.khpi.tarasenko.bach.core.db.DBUtils;
import ua.kharkov.khpi.tarasenko.bach.core.db.EShopDataStoreException;
import ua.kharkov.khpi.tarasenko.bach.core.logging.CustomerSession;
import ua.kharkov.khpi.tarasenko.bach.core.logging.TransTypePair;
import ua.kharkov.khpi.tarasenko.bach.dao.core.DAOFactory;
import ua.kharkov.khpi.tarasenko.bach.dao.core.DAOFactory.DAO_TYPE;
import ua.kharkov.khpi.tarasenko.bach.dao.core.item.ItemDAO;
import ua.kharkov.khpi.tarasenko.bach.dao.core.item.ItemDTO;
import ua.kharkov.khpi.tarasenko.bach.dao.core.usersession.UserSessionDAO;
import ua.kharkov.khpi.tarasenko.bach.service.AnalysisService;

public class SolTestingDemo {

	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws Exception {
		//
		// generateItems(2500);
		//
		// buildAndSaveTree();
		// generateItems(2500);

		PseudoDbPS db = FileUtils.getDBFromFile(new File(
				"/home/oleksandr/Desktop/bach_projection/transact_train.txt"));
		System.out.println(db.size);
		//		loadStartLogsToDB(db);

		//
		//
		//
		//
		//
		//

		// Node rootNode1 = analServ.getTreeFromDB();
		//
		//
		// Set<Item> recs1 = RulesGenerator.getRecommendation(rootNode1,
		// currentSeq, 0, 10);
		// System.out.println("=========================================");
		// for(Item rItem : recs1) {
		// System.out.println(rItem);
		// }

		// long start = System.currentTimeMillis();
		//
		// PseudoDB db = FileUtils.getDBFromFile(new File(
		// "/home/oleksandr/Desktop/bach_projection/transact_train.txt"));
		// System.out.println(db.getRows().size());
		// db = AnalysisUtils.removeNonBuySessions(db);
		// System.out.println(db.getRows().size());
		//
		// SolutionTester tester = new SolutionTester(db, 400);
		// tester.testSolution(new GeneralAnalysis());
		// //
		// //
		// // // int maxId = getMaxItemId(db);
		// // // System.out.println("Max id = " + maxId);
		// // // generateItems(maxId);
		// // // loadStartLogsToDB(db);
		// // //
		// long finish = System.currentTimeMillis();
		// System.out.println("It took " + (finish - start));

		// PseudoDB db = FileUtils.getDBFromFile(new File(
		// "/java/workspace/eclipse/solutions_tester/src/main/resources/[test2]transact_train.txt"));
		// System.out.println(db.getRows().size());
		// db = AnalysisUtils.removeNonBuySessions(db);
		// System.out.println(db.getRows().size());

		// File nf = new
		// File("C:/Users/Oleksandr_Tarasenko/Desktop/bach_projection/transact_train1.txt");
		// BufferedWriter bw = new BufferedWriter(new FileWriter(nf));
		// for(Sequence s: db.getRows()) {
		// bw.write(s.toString());
		// bw.newLine();
		// }
		// // bw.close();
		//
		//
		// SolutionTester tester = new SolutionTester(db, 200);
		// tester.testSolution(new GeneralAnalysis());
		// //
		// //
		// // // int maxId = getMaxItemId(db);
		// // // System.out.println("Max id = " + maxId);
		// // // generateItems(maxId);
		// // // loadStartLogsToDB(db);
		// // //
		// long finish = System.currentTimeMillis();
		// System.out.println("It took " + (finish - start));

		// PseudoDbPS db = FileUtils
		// .getDBFromFile(new File(
		// "C:/Users/Oleksandr_Tarasenko/Desktop/bach_projection/transact_train.txt"));
		// testGetBoughtItemSets(db);

	}

	// private static void testTreeOnTestSet() {
	// Sequence currentSeq = new Sequence();
	// item = Item.getItem("3");
	// item.setTransactionType(TransactionType.VIEW);
	// currentSeq.addItem(item);
	// item = Item.getItem("1");
	// item.setTransactionType(TransactionType.VIEW);
	// currentSeq.addItem(item);
	// item = Item.getItem("2");
	// item.setTransactionType(TransactionType.BUY);
	// currentSeq.addItem(item);
	// }

	private static void buildAndSaveTree() throws IOException {
		AnalysisService analServ = new AnalysisService();
		analServ.deleteTreeFromDB();

		PseudoDbPS db = FileUtils.getDBFromFile(new File(
				"/home/oleksandr/Desktop/bach_projection/transact_train.txt"));
		db = AnalysisUtils.getAccessDB(db);
		System.out.println("DB build");

		Timer t = new Timer();
		t.schedule(new TimerTask() {

			@Override
			public void run() {
				double currentMemory = (Runtime.getRuntime().totalMemory() - Runtime
						.getRuntime().freeMemory()) / 1024d / 1024d;
				System.out.println(currentMemory);

			}
		}, new Date(), 15000);
		analServ.deleteTreeFromDB();
		PrefixSpanAlgorythm ps = new PrefixSpanAlgorythm();
		Node rootNode = ps.analyze(db, 40);
		System.out.println("Analyse finished");

		analServ.saveTreeToDB(rootNode);
		System.out.println("Saving finished");
	}

	private static void testRulesFindingDeletingCounting() {

		AnalysisService serv = new AnalysisService();
		System.out.println("Rules in DB:" + serv.getNumberOfRulesInDb());

		Integer[] itemsInCart = new Integer[3];
		itemsInCart[0] = 1;
		itemsInCart[1] = 2;
		itemsInCart[2] = 4;

		Integer[] recs = serv.getDontForgetRecommendations(itemsInCart, 3);
		System.out.println(Arrays.toString(recs));

		serv.deleteRules();
		System.out.println("Rules in DB:" + serv.getNumberOfRulesInDb());
	}

	private static void testTNRAlgo() throws IOException,
			EShopDataStoreException {
		System.out.println("Test started, " + new Date());
		PseudoDbPS db = FileUtils
				// .getDBFromFile(new File(
				// "D:/workspaces/edu/solutions_tester/src/main/resources/[test2]transact_train.txt"));
				.getDBFromFile(new File(
						"C:/Users/Oleksandr_Tarasenko/Desktop/bach_projection/transact_train.txt"));

		System.out.println("DB loaded, " + new Date());
		db = AnalysisUtils.getBoughtItemSets(db);
		System.out.println("Got bought itemsets, " + new Date());
		AlgoTNR tnr = new AlgoTNR();

		int k = 2000;
		double minConfidence = 0.7;
		PseudoDbTNR database = AnalysisUtils.transformPSToTRNDb(db);
		int delta = 100;

		Timer t = new Timer();
		t.schedule(new TimerTask() {

			@Override
			public void run() {
				double currentMemory = (Runtime.getRuntime().totalMemory() - Runtime
						.getRuntime().freeMemory()) / 1024d / 1024d;
				System.out.println(currentMemory);

			}
		}, new Date(), 15000);

		RedBlackTree<RuleG> rules = tnr.runAlgorithm(k, minConfidence,
				database, delta);
		System.out.println("Analysis finished, " + new Date());

		System.out.println(tnr.notAdded);
		System.out.println(tnr.totalremovedCount);

		AnalysisService serv = new AnalysisService();
		serv.saveRules(rules);
		System.out.println("Saving finished, " + new Date());
	}

	private static int getMaxItemId(PseudoDbPS db) {
		int maxId = 0;

		for (Sequence seq : db.getRows()) {
			for (Item item : seq.getItems()) {
				maxId = maxId > Integer.valueOf(item.getItem()) ? maxId
						: Integer.valueOf(item.getItem());
			}
		}
		return maxId;
	}

	private static void loadStartLogsToDB(PseudoDbPS db) throws SQLException {

		Connection conn = null;
		try {
			conn = DriverManager.getConnection("jdbc:mysql://localhost/eshop",
					"root", "root");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		List<CustomerSession> sessions = new ArrayList<CustomerSession>();
		for (Sequence seq : db.getRows()) {
			CustomerSession session = new CustomerSession();
			List<TransTypePair> transactions = new ArrayList<TransTypePair>();
			for (Item item : seq.getItems()) {
				TransTypePair pair = new TransTypePair(Integer.parseInt(item.getItem()), item.getTransactionType());
				transactions.add(pair);
			}			
			session.setTransactions(transactions);
			sessions.add(session);
		}
		
		
		try {
			UserSessionDAO userSessionDAO = DAOFactory.getDAOFactory(
					DAO_TYPE.MYSQL).getUserSessionDAO(conn);
			for (CustomerSession session : sessions) {
				userSessionDAO.saveSession(session);
			}
			DBUtils.commitAndClose(conn);
		} catch (EShopException e) {
			System.err.println("Cant do rollout of logs!");
		} finally {
			DBUtils.close(conn);
		}
		
//		
//		for (Sequence seq : db.getRows()) {
//			PreparedStatement psSession = conn.prepareStatement(
//					"INSERT INTO SESSION() VALUES()",
//					Statement.RETURN_GENERATED_KEYS);
//			PreparedStatement psTransaction = conn
//					.prepareStatement("INSERT INTO TRANSACTION(SESSION_ID, ITEM_ID, TRANSACTION_TYPE) VALUES(?,?,?)");
//
//			ResultSet rs = null;
//			psSession.executeUpdate();
//			rs = psSession.getGeneratedKeys();
//			rs.next();
//			int sessionId = rs.getInt(1);
//
//			for (Item item : seq.getItems()) {
//				psTransaction.setInt(1, sessionId);
//				psTransaction.setInt(2, Integer.valueOf(item.getItem()));
//				psTransaction.setInt(3, item.getTransactionType().ordinal());
//
//				psTransaction.executeUpdate();
//			}
//			rs.close();
//			psTransaction.close();
//			psSession.close();
//		}

		// Session hibernateSession = HibernateUtil.getSession();
		// UserSessionDAO userSessionDAO = new
		// UserSessionDAOImpl(hibernateSession);
		// Transaction transaction = hibernateSession.beginTransaction();
		//
		// for (Sequence seq : db.getRows()) {
		// CustomerSession session = new CustomerSession();
		//
		// for (Item item : seq.getItems()) {
		// TransTypePair tp = new TransTypePair(Integer.valueOf(item
		// .getItem()), item.getTransactionType());
		// session.addTransaction(tp);
		// }
		// userSessionDAO.save(session);
		// }
		//
		// transaction.commit();
		// hibernateSession.close();

	}

	private static void generateItems(int num) throws EShopDataStoreException,
			EShopException, SQLException {

		Connection conn = null;
		try {
			conn = DriverManager.getConnection("jdbc:mysql://localhost/eshop",
					"root", "root");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		PreparedStatement ps = conn
				.prepareStatement("SET SESSION sql_mode='NO_AUTO_VALUE_ON_ZERO'");
		ps.executeUpdate();

		ItemDAO itemDAO = DAOFactory.getDAOFactory(DAO_TYPE.MYSQL).getItemDAO(
				conn);

		for (int i = 1; i <= num; i++) {
			ItemDTO itemDTO = new ItemDTO();
			itemDTO.setId(i);
			itemDTO.setCategory((int) Math.round(Math.random() * 4));
			itemDTO.setDescription("Autogenerated item " + i);
			itemDTO.setName("Item " + i);
			itemDTO.setQuantity(1);
			itemDTO.setPrice(i);

			itemDAO.addItem(itemDTO);
		}
	}

	public static void testGetBoughtItemSets(PseudoDbPS db) {
		PseudoDbPS itemSets = AnalysisUtils.getBoughtItemSets(db);
		System.out.println(itemSets);
		System.out.println(itemSets.size);
	}
}
